package com.koron.order.risk.base.service.impl;


import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.koron.bean.base.BaseBean;
import com.koron.bean.query.PageQuery;
import com.koron.bean.system.org.OrgBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.OrgCacheUtils;
import com.koron.order.linepatrol.satellite.service.LinePatrolReferer;
import com.koron.order.risk.base.bean.convertor.LineRiskConvertor;
import com.koron.order.risk.base.bean.dto.LineRiskDTO;
import com.koron.order.risk.base.bean.param.LineRiskCancelParam;
import com.koron.order.risk.base.bean.po.*;
import com.koron.order.risk.base.bean.query.LineKeyRiskQuery;
import com.koron.order.risk.base.bean.query.LineRiskQuery;
import com.koron.order.risk.base.bean.vo.LineKeyRiskVO;
import com.koron.order.risk.base.bean.vo.LineRiskVO;
import com.koron.order.risk.base.mapper.LineRiskMapper;
import com.koron.order.risk.base.service.*;
import com.koron.order.risk.feign.LineEquipmentFeign;
import com.koron.order.risk.riskDuty.bean.vo.LineRiskDutyVO;
import com.koron.order.risk.riskDuty.service.LineRiskDutyService;
import com.koron.order.risk.util.LineRiskConstant;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 风险管控单(LineRisk)表服务实现类
 *
 * @author jzp
 * @since 2022-12-15 16:17:58
 */
@Service
public class LineRiskServiceImpl implements LineRiskService {

    @Autowired
    private LineRiskDetailBuildingService lineRiskDetailBuildingService;
    @Autowired
    private LineRiskDetailConstructionService lineRiskDetailConstructionService;
    @Autowired
    private LineRiskDetailDefaultService lineRiskDetailDefaultService;
    @Autowired
    private LineRiskEliminateService lineRiskEliminateService;
    @Autowired
    private LineRiskMeasureService lineRiskMeasureService;
    @Autowired
    private LineRiskDutyService lineRiskDutyService;
    @Autowired
    private LineRiskPartService lineRiskPartService;
    @Autowired
    private LineRiskConvertor lineRiskConvertor;
    @Autowired
    private LinePatrolReferer linePatrolReferer;
    @Autowired
    private LineEquipmentFeign lineEquipmentFeign;

    /**
     * 通过ID查询单条数据
     *
     */
    @Override
    @TaskAnnotation("getById")
    public LineRiskVO getById(SessionFactory factory, String id) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        LineRiskVO lineRiskVO = mapper.selectById(id);
        List<LineRiskPart> lineRiskPartList = lineRiskPartService.listByRiskId(factory, id);
        lineRiskVO.setLineRiskPartList(lineRiskPartList);
        return lineRiskVO;
    }

    @Override
    @TaskAnnotation("getByIdAndKeyLevel")
    public LineKeyRiskVO getByIdAndKeyLevel(SessionFactory factory, String id) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        LineKeyRiskVO lineKeyRiskVO = mapper.selectByIdAndKeyLevel(id);
        List<LineRiskPart> lineRiskPartList = lineRiskPartService.listByRiskId(factory, id);
        lineKeyRiskVO.setLineRiskPartList(lineRiskPartList);
        return lineKeyRiskVO;
    }

    @Override
    @TaskAnnotation("getDtoById")
    public LineRiskDTO getDtoById(SessionFactory factory, String id) {
        // 查询基础信息
        LineRiskVO lineRiskVO = getById(factory, id);
        LineRiskDTO lineRiskDTO = lineRiskConvertor.voToDto(lineRiskVO);

        // 待审核状态才有管控措施
        if (LineRiskConstant.Status.getStatusWeight(lineRiskDTO.getStatus()) > 0) {
            LineRiskMeasure lineRiskMeasure = new LineRiskMeasure();
            lineRiskMeasure.setRiskId(id);
            List<LineRiskMeasure> list = lineRiskMeasureService.list(factory, lineRiskMeasure);
            lineRiskDTO.setLineRiskMeasureList(list);

            // 如果已有新增看护值守，则不允许新增
            for (LineRiskMeasure riskMeasure : list) {
                if (!"4".equals(riskMeasure.getControlMeasures())) {
                    continue;
                }
                LineRiskDutyVO oneByRiskId = lineRiskDutyService.getOneByRiskId(factory, id);
                if (oneByRiskId != null) {
                    riskMeasure.setHasAddDuty(1);
                    riskMeasure.setLineRiskDutyVO(oneByRiskId);
                }
                break;
            }
        }

        // 风险管控中状态才有风险详情
        if (LineRiskConstant.Status.getStatusWeight(lineRiskDTO.getStatus()) > 1) {
            if ("施工作业区".equals(lineRiskDTO.getRiskKeyword())) {
                LineRiskDetailConstruction lineRiskDetailConstruction = lineRiskDetailConstructionService.getOneByRiskId(factory, id);
                lineRiskDTO.setLineRiskDetailConstruction(lineRiskDetailConstruction);
            } else if ("违章建筑".equals(lineRiskDTO.getRiskKeyword())) {
                LineRiskDetailBuilding lineRiskDetailBuilding = lineRiskDetailBuildingService.getOneByRiskId(factory, id);
                lineRiskDTO.setLineRiskDetailBuilding(lineRiskDetailBuilding);
            } else {
                LineRiskDetailDefault lineRiskDetailDefault = lineRiskDetailDefaultService.getOneByRiskId(factory, id);
                lineRiskDTO.setLineRiskDetailDefault(lineRiskDetailDefault);
            }
        }

        // 风险消除审核状态才有消除审核
        if (LineRiskConstant.Status.getStatusWeight(lineRiskDTO.getStatus()) > 2) {
            LineRiskEliminate lineRiskEliminate = lineRiskEliminateService.getOneByRiskId(factory, id);
            lineRiskDTO.setLineRiskEliminate(lineRiskEliminate);
        }

        // 风险已归档状态才有
        if (LineRiskConstant.Status.getStatusWeight(lineRiskDTO.getStatus()) > 3) {

        }

        return lineRiskDTO;
    }

    @Override
    @TaskAnnotation("listAndKeyLevel")
    public List<LineKeyRiskVO> listAndKeyLevel(SessionFactory factory, LineKeyRiskQuery query) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        List<LineKeyRiskVO> lineRiskVOS = mapper.selectListAndKeyLevel(query);
        if (CollUtil.isEmpty(lineRiskVOS)) {
            return lineRiskVOS;
        }
        List<String> ids = lineRiskVOS.stream().map(BaseBean::getId).collect(Collectors.toList());
        List<LineRiskPart> lineRiskPartList = lineRiskPartService.listByRiskIds(factory, ids);
        if (CollUtil.isEmpty(lineRiskPartList)) {
            return lineRiskVOS;
        }
        Map<String, List<LineRiskPart>> lineRiskPartMap = lineRiskPartList.stream().collect(Collectors.groupingBy(LineRiskPart::getRiskId, LinkedHashMap::new, Collectors.toList()));
        lineRiskVOS.forEach(e -> e.setLineRiskPartList(lineRiskPartMap.get(e.getId())));
        return lineRiskVOS;
    }

    /**
     * 查询所有数据
     *
     */
    @Override
    @TaskAnnotation("list")
    public List<LineRiskVO> list(SessionFactory factory, LineRiskQuery query) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        List<LineRiskVO> lineRiskVOS = mapper.selectList(query);
        if (CollUtil.isEmpty(lineRiskVOS)) {
            return lineRiskVOS;
        }
        List<String> ids = lineRiskVOS.stream().map(BaseBean::getId).collect(Collectors.toList());
        List<LineRiskPart> lineRiskPartList = lineRiskPartService.listByRiskIds(factory, ids);
        if (CollUtil.isEmpty(lineRiskPartList)) {
            return lineRiskVOS;
        }
        Map<String, List<LineRiskPart>> lineRiskPartMap = lineRiskPartList.stream().collect(Collectors.groupingBy(LineRiskPart::getRiskId, LinkedHashMap::new, Collectors.toList()));
        lineRiskVOS.forEach(e -> e.setLineRiskPartList(lineRiskPartMap.get(e.getId())));
        return lineRiskVOS;
    }

    public List<LineRiskVO> listOfDuty(SessionFactory factory, LineRiskQuery query) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        List<LineRiskVO> lineRiskVOS = mapper.selectListOfDuty(query);
        if (CollUtil.isEmpty(lineRiskVOS)) {
            return lineRiskVOS;
        }
        List<String> ids = lineRiskVOS.stream().map(BaseBean::getId).collect(Collectors.toList());
        List<LineRiskPart> lineRiskPartList = lineRiskPartService.listByRiskIds(factory, ids);
        if (CollUtil.isEmpty(lineRiskPartList)) {
            return lineRiskVOS;
        }
        Map<String, List<LineRiskPart>> lineRiskPartMap = lineRiskPartList.stream().collect(Collectors.groupingBy(LineRiskPart::getRiskId, LinkedHashMap::new, Collectors.toList()));
        lineRiskVOS.forEach(e -> e.setLineRiskPartList(lineRiskPartMap.get(e.getId())));
        return lineRiskVOS;
    }

    @Override
    @TaskAnnotation("listDetail")
    public List<LineRiskDTO> listDetail(SessionFactory factory, LineRiskQuery query) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        List<LineRiskDTO> lineRiskDTOS = mapper.selectListAndDetail2(query);
        if (CollUtil.isEmpty(lineRiskDTOS)) {
            return lineRiskDTOS;
        }
        List<String> ids = lineRiskDTOS.stream().map(BaseBean::getId).collect(Collectors.toList());
        List<LineRiskPart> lineRiskPartList = lineRiskPartService.listByRiskIds(factory, ids);
        if (CollUtil.isEmpty(lineRiskPartList)) {
            return lineRiskDTOS;
        }
        Map<String, List<LineRiskPart>> lineRiskPartMap = lineRiskPartList.stream().collect(Collectors.groupingBy(LineRiskPart::getRiskId, LinkedHashMap::new, Collectors.toList()));
        lineRiskDTOS.forEach(e -> e.setLineRiskPartList(lineRiskPartMap.get(e.getId())));
        return lineRiskDTOS;
    }

    @Override
    @TaskAnnotation("page")
    public PageInfo<LineRiskVO> page(SessionFactory factory, PageQuery pageQuery, LineRiskQuery query) {
        pageQuery.unPrefixOrders("lineRisk", Arrays.asList("currNodeName",
                "currNodeUser",
                "currNodeCode"));
        PageHelper.startPage(pageQuery.getPage(), pageQuery.getPageSize(), pageQuery.getOrderBy());
        List<LineRiskVO> lineRiskList;

        /*
         * （1）只具有本人数据权限：创建人、工单涉及的审批人、负责人、验收人均能看到和自己相关的数据；
         * （2）各个供水管理部只能看到跟进部门为自己供水管理部下的数据；
         * （3）维修部、技术部以及领导能看到所有的数据；
         */
        EamUser eamUser = ThreadLocalContext.get();
        if (eamUser.getCurrDs().equals("water_02") &&  eamUser.getDeptName().endsWith("供水管理部")) {
            List<OrgBean> orgBeans = OrgCacheUtils.queryOrgListByParentId(eamUser.getDeptId());
            List<String> orgIds = orgBeans.stream().map(BaseBean::getId).collect(Collectors.toList());
            orgIds.add(eamUser.getDeptId());
            query.setFollowDeptIds(orgIds);
        }

        // 查询优化，如果需要根据管控措施进行查询
        if (query.getControlMeasures() != null || query.getLeaderId() != null || query.getLeaderName() != null) {
            lineRiskList = listOfDuty(factory, query);
        } else {
            lineRiskList = list(factory, query);
        }
        return new PageInfo<>(lineRiskList);
    }

    /**
     * 新增数据
     *
     */
    @Override
    @TaskAnnotation("save")
    public boolean save(SessionFactory factory, LineRiskVO lineRiskVO) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        if (lineRiskVO.getStatus() == null) {
            lineRiskVO.setStatus(LineRiskConstant.Status.DRAFT);
        }
        if (lineRiskVO.getCode() == null) {
            lineRiskVO.setCode(CodeTools.getCodeNo(codePrefix, 3));
        }
        // 保存主表信息
        mapper.insertOrUpdate(lineRiskVO);

        // 保存塔段
        savePart(factory, lineRiskVO.getId(), lineRiskVO.getLineRiskPartList());

        // 关联卫星巡视等
        if (LineRiskConstant.Status.DRAFT.equals(lineRiskVO.getStatus())) {
            linePatrolReferer.refRisk(factory, lineRiskVO);
        }
        return true;
    }

    @Override
    @TaskAnnotation("savePart")
    public boolean savePart(SessionFactory factory, String riskId, List<LineRiskPart> lineRiskPartList) {
        lineRiskPartService.removeByRiskId(factory, riskId);
        if (lineRiskPartList == null) {
            return false;
        }
        // 如果未保存过设备经纬度信息，则去保存设备经纬度信息
        lineRiskPartList.stream()
                .findFirst()
                .map(LineRiskPart::getLatitude)
                .ifPresent(e -> {
                    List<String> equipmentIds = lineRiskPartList.stream().map(LineRiskPart::getEquipmentId).collect(Collectors.toList());
                    // equipmentId -> list<param>
                    Map<String, Map<String, String>> paramsMap = lineEquipmentFeign.getTowerParams(equipmentIds).getData();
                    // 拿到该设备的经纬度
                    for (LineRiskPart lineRiskPart : lineRiskPartList) {
                        Map<String, String> map = paramsMap.get(lineRiskPart.getEquipmentId());
                        String longitude = map.getOrDefault("longitude", null);
                        String latitude = map.getOrDefault("latitude", null);
                        lineRiskPart.setLongitude(longitude);
                        lineRiskPart.setLatitude(latitude);
                    }
                });

        lineRiskPartList.forEach(e -> e.setRiskId(riskId));
        IntStream.range(0, lineRiskPartList.size())
                .forEach(i -> lineRiskPartList.get(i).setSort(i));
        lineRiskPartService.saveBatch(factory, lineRiskPartList);
        return true;
    }

    @Override
    @TaskAnnotation("saveDto")
    public LineRiskDTO saveDto(SessionFactory factory, LineRiskDTO lineRiskDTO) {
        // 设置落实状态
        String workableStatus = lineRiskDTO.computeWorkableStatus();
        lineRiskDTO.setWorkableStatus(workableStatus);
        // 保存主表数据
        save(factory, lineRiskDTO);
        String riskId = lineRiskDTO.getId();

        // 保存管控措施
        lineRiskMeasureService.removeByRiskId(factory, riskId);
        if (lineRiskDTO.getLineRiskMeasureList() != null) {
            lineRiskDTO.getLineRiskMeasureList().forEach(e -> e.setRiskId(riskId));
        }
        lineRiskMeasureService.saveBatch(factory, lineRiskDTO.getLineRiskMeasureList());

        // 保存风险详情
        if (lineRiskDTO.getLineRiskDetailConstruction() != null) {
            lineRiskDTO.getLineRiskDetailConstruction().setRiskId(riskId);
            lineRiskDetailConstructionService.save(factory, lineRiskDTO.getLineRiskDetailConstruction());
        }
        if (lineRiskDTO.getLineRiskDetailBuilding() != null) {
            lineRiskDTO.getLineRiskDetailBuilding().setRiskId(riskId);
            lineRiskDetailBuildingService.save(factory, lineRiskDTO.getLineRiskDetailBuilding());
        }
        if (lineRiskDTO.getLineRiskDetailDefault() != null) {
            lineRiskDTO.getLineRiskDetailDefault().setRiskId(riskId);
            lineRiskDetailDefaultService.save(factory, lineRiskDTO.getLineRiskDetailDefault());
        }

        // 保存消除审核
        if (lineRiskDTO.getLineRiskEliminate() != null) {
            lineRiskDTO.getLineRiskEliminate().setRiskId(riskId);
            lineRiskEliminateService.save(factory, lineRiskDTO.getLineRiskEliminate());
        }

        return lineRiskDTO;
    }

    /**
     * 增量批量新增，不会删除原有数据
     */
    @Override
    @TaskAnnotation("saveBatch")
    public boolean saveBatch(SessionFactory factory, List<LineRiskVO> lineRiskVOList) {
        if (CollUtil.isEmpty(lineRiskVOList)) {
            return false;
        }
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        for (LineRiskVO lineRiskVO : lineRiskVOList) {
            if (lineRiskVO.getStatus() == null) {
                lineRiskVO.setStatus(LineRiskConstant.Status.DRAFT);
            }
            if (lineRiskVO.getCode() == null) {
                lineRiskVO.setCode(CodeTools.getCodeNo("FXGK", 3));
            }
        }

        // 保存主表信息
        List<LineRisk> lineRiskList = lineRiskConvertor.voListToPoList(lineRiskVOList);
        mapper.insertOrUpdateBatch(lineRiskList);

        // 保存塔段
        for (int i = 0; i < lineRiskVOList.size(); i++) {
            LineRiskVO lineRiskVO = lineRiskVOList.get(i);
            List<LineRiskPart> lineRiskPartList = lineRiskVO.getLineRiskPartList();
            if (CollUtil.isEmpty(lineRiskPartList)) {
                lineRiskVO.setLineRiskPartList(new ArrayList<>());
                continue;
            }
            for (int j = 0; j < lineRiskPartList.size(); j++) {
                lineRiskPartList.get(j).setRiskId(lineRiskList.get(i).getId());
                lineRiskPartList.get(j).setSort(j);
            }
        }
        List<LineRiskPart> collect = lineRiskVOList.stream().flatMap(e -> e.getLineRiskPartList().stream()).collect(Collectors.toList());
        lineRiskPartService.saveBatch(factory, collect);
        return true;
    }

    /**
     * 修改数据
     *
     */
    @Override
    @TaskAnnotation("update")
    public boolean update(SessionFactory factory, LineRisk lineRisk) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        return mapper.update(lineRisk) > 0;
    }

    @Override
    @TaskAnnotation("updateStatus")
    public boolean updateStatus(SessionFactory factory, String id, String status) {
        LineRisk lineRisk = new LineRisk();
        lineRisk.setId(id);
        lineRisk.setStatus(status);
        return update(factory, lineRisk);
    }

    @Override
    @TaskAnnotation("submit")
    public boolean submit(SessionFactory factory, LineRiskDTO lineRiskDTO, String currNodeCode) {
        // 草稿
        if (currNodeCode == null || currNodeCode.contains(LineRiskConstant.Status.DRAFT)) {
            return updateStatus(factory, lineRiskDTO.getId(), LineRiskConstant.Status.DRAFT);
        }
        // 待审核
        else if (currNodeCode.contains(LineRiskConstant.Status.WAIT_REVIEW)) {
            return updateStatus(factory, lineRiskDTO.getId(), LineRiskConstant.Status.WAIT_REVIEW);
        }
        // 风险管控中
        else if (currNodeCode.contains(LineRiskConstant.Status.MANAGEMENT)) {
            return updateStatus(factory, lineRiskDTO.getId(), LineRiskConstant.Status.MANAGEMENT);
        }
        // 消除审核
        else if (currNodeCode.contains(LineRiskConstant.Status.ELIMINATE_REVIEW)) {
            // 如果有看护值守单，需要结束
            LineRiskDutyVO lineRiskDutyVO = lineRiskDutyService.getOneByRiskId(factory, lineRiskDTO.getId());
            if (lineRiskDutyVO != null) {
                lineRiskDutyService.end(factory, lineRiskDutyVO.getId());
            }
            return updateStatus(factory, lineRiskDTO.getId(), LineRiskConstant.Status.ELIMINATE_REVIEW);
        }
        // 已归档
        else if (currNodeCode.equals("END") || currNodeCode.contains(LineRiskConstant.Status.ARCHIVED)) {
            return updateStatus(factory, lineRiskDTO.getId(), LineRiskConstant.Status.ARCHIVED);
        }
        return false;
    }

    /**
     * 针对风险判定失误导致工单无法正常完
     * 成的场景，可以通过将工单作废来做特殊处理。仅
     * 待审核状态的风险管控单可以被作废
     */
    @Override
    @TaskAnnotation("cancel")
    public boolean cancel(SessionFactory factory, LineRiskCancelParam param) {
        List<String> ids = param.getIds();
        LineRiskQuery lineRiskQuery = new LineRiskQuery();
        lineRiskQuery.setIds(ids);
        List<LineRiskVO> list = list(factory, lineRiskQuery);
        Assert.notEmpty(list, "未找到作废数据");
        boolean b = list.stream().map(LineRisk::getStatus).allMatch(LineRiskConstant.Status.WAIT_REVIEW::equals);
        Assert.isTrue(b, "待审核状态的数据才可以被作废");
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        return mapper.cancelBatch(param.getIds(), param.getCancelReason()) > 0;
    }

    @Override
    @TaskAnnotation("finishDuty")
    public boolean finishDuty(SessionFactory factory, String id) {
        LineRiskMeasure lineRiskMeasure = new LineRiskMeasure();
        lineRiskMeasure.setRiskId(id);
        List<LineRiskMeasure> list = lineRiskMeasureService.list(factory, lineRiskMeasure);
        // 1. 查询看护值守数据
        if (CollUtil.isEmpty(list)) {
            return false;
        }
        list.stream().filter(e -> "4".equals(e.getControlMeasures()))
                .findFirst()
                .ifPresent(riskMeasure -> {
                    riskMeasure.setImplemented(1);
                    lineRiskMeasureService.save(factory, riskMeasure);
                });

        return true;
    }

    /**
     * 通过主键删除数据
     *
     */
    @Override
    @TaskAnnotation("deleteById")
    public boolean deleteById(SessionFactory factory, String id) {
        LineRiskMapper mapper = factory.getMapper(LineRiskMapper.class);
        return mapper.hidden(id) > 0;
    }
}
